<template>
  <div class="hello">
    <p ref="p">{{ num }}</p>
    <button @click="add">add</button>
  </div>
</template>

<script>
//#region
/*
  更新组件流程：
    1. this.num++;
    2. 触发数据代理的set方法
    3. 触发数据劫持的set方法
      更新响应式数据
      同时，调用dep.notify()
    4. dep.notify()
      遍历 subs 数组（保存所有与之相关的watcher）
      调用 watcher.update() 更新
        将watcher添加到queue中保管，queue会塞入一个函数（flushSchedulerQueue），
        flushSchedulerQueue塞入到nextTick方法，放入的异步微任务执行（所以更新时异步的）
    5. watcher.update()
      this.run()
        this.get()
          this.getter()
            updateComponent
    6. updateComponent
      this._render 得到新的虚拟DOM对象树
      this._update 更新
    7. this._update
      this.__patch__
    8. patch
      得到新旧两个虚拟DOM对象树
      patchVnode 进行比较
    9. patchVnode
      判断是否是静态节点 return  
      判断新的是否有文本内容
        没有
          判断是否有子元素（children）
            都有子元素
              updateChildren对子元素进行比较
            新的有子元素（旧的没有）
              直接将新的子元素添加到DOM上
            旧的有子元素（新的没有）
              将DOM中的旧子元素删除
            都没有子元素
              判断旧的是否有文本内容
                有 清空文本内容
        有
          判断文本内容是否相等
            不能相等就更新DOM  
      10. updateChildren
        oldStart 旧前
        oldEnd   旧后
        newStart 新前
        newEnd   新后      
        
        - 判断旧前和新前是否是sameVnode（相同的虚拟DOM对象）
          如果是调用 patchVnode 对两个元素进行进一步比较并更新
          将 旧前 和 新前 坐标递增

        - 判断旧后和新后是否是sameVnode（相同的虚拟DOM对象）
          如果是调用 patchVnode 对两个元素进行进一步比较并更新
          将 旧后 和 新后 坐标递减
        
        - 判断旧前和新后是否是sameVnode（相同的虚拟DOM对象）
          如果是调用 patchVnode 对两个元素进行进一步比较并更新
          移动DOM元素的位置
          将 旧前 坐标递增   
             新后 坐标递减
        
        - 判断旧后和新前是否是sameVnode（相同的虚拟DOM对象）
          如果是调用 patchVnode 对两个元素进行进一步比较并更新
          移动DOM元素的位置
          将 旧后 坐标递减 
             新前 坐标递增
        
        - 如果都不是，提取旧的（start-end）所有key
          提取新的start元素，判断新的start元素的key是否在旧的（start-end）所有key中
            在
              找到下标
            不在
              遍历旧的（start-end）去找是否有相同的元素
          判断下标是否存在
            存在
              判断新旧两个元素是否是sameVnode
                是
                  如果是调用 patchVnode 对两个元素进行进一步比较并更新
                  移动DOM元素的位置
                不是（key相同，但元素变了，往往说明index做为key的问题）
                  元素重新创建
            不存在
              直接创建新元素    
          
          最后做完，新前 坐标递增
*/
//#endregion
export default {
  name: "HelloWorld",
  data() {
    return {
      num: 0,
    };
  },
  methods: {
    add() {
      // debugger;
      this.$nextTick(() => {
        // 将函数放入异步微任务执行
        // 如果是在 this.num++; 之前调用的
        // 那函数实际上就是在更新DOM元素之前触发，此时获取不到最新的DOM
        console.log(this.$refs.p.textContent); // 0
      });
      this.num++;
      this.$nextTick(() => {
        // 如果想要获取最新的DOM，就要在更新数据之后调用
        console.log(this.$refs.p.textContent); // 1
      });
    },
  },
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
